package com.ruoyi.sms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.infobip.ApiException;
import com.infobip.api.SendSmsApi;
import com.infobip.model.SmsPreviewRequest;
import com.infobip.model.SmsPreviewResponse;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.dto.UserInfo;
import com.ruoyi.bizsys.mapper.LoanIouMapper;
import com.ruoyi.bizsys.mapper.ProductDeferredInfoMapper;
import com.ruoyi.bizsys.mapper.ProductRelationDeferredMapper;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.bizsys.utils.UserCacheService;
import com.ruoyi.bizsys.vo.MonnifyReservedAccount;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RspEnmu;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.VerifyCodeUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.sms.common.Constants;
import com.ruoyi.sms.common.SmsUtil;
import com.ruoyi.sms.config.SmsConfigTool;
import com.ruoyi.sms.config.SmsSendConfig;
import com.ruoyi.sms.config.VerifyCodeConfigTool;
import com.ruoyi.sms.domain.SmsSendData;
import com.ruoyi.sms.domain.SmsSendReq;
import com.ruoyi.sms.domain.SmsSendVo;
import com.ruoyi.sms.mapper.SmsSendMapper;
import com.ruoyi.sms.service.ISmsService;
import com.ruoyi.sms.util.SmsSignUtil;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: Jamnsin
 * @Date: 2021/1/13 4:11 下午
 */
@Slf4j
@Service
public class SmsServiceImpl implements ISmsService {

    @Autowired
    SmsConfigTool smsConfig;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    ISmsTemplateService smsTemplateService;

    @Autowired
    ISmsSendLogService smsSendLogService;

    @Autowired
    SmsSendMapper smsMapper;

    @Autowired
    VerifyCodeConfigTool verifyCodeConfig;

    @Autowired
    IVerifyCodeLogService verifyCodeLogService;

    @Autowired
    ISysDictDataService sysDictDataService;

    @Autowired
    IRepaymentOrderService repaymentOrderService;

    @Autowired
    private IRealNameAuthService realNameAuthService;

    @Autowired
    private UserCacheService userCacheService;

    @Autowired
    private ILoanOrderService orderService;

    @Autowired
    ISysConfigService sysConfigService;

    @Autowired
    ProductDeferredInfoMapper deferredInfoMapper;

    @Autowired
    IProductDeferredInfoService productDeferredInfoService;

    @Autowired
    ProductRelationDeferredMapper productRelationDeferredMapper;


    public static String PARAM_MARK = "#";

    public static final String SUCCESSFUL = "successful";
    public static final String DISABLED = "disabled";
    public static final String FAILURE = "failure";

    /**
     * 短信发送工具类
     */
    private SmsUtil smsUtil = new SmsUtil();

    private SmsSignUtil smsSignUtil = new SmsSignUtil();

    @Autowired
    SmsSendConfig smsSendConfig;

    @Autowired
    private LoanIouMapper loanIouMapper;

    @Override
    public SmsSendData sendVerifyCode(SmsSendReq smsReq, boolean checkInterval) {
        if (StringUtils.isBlank(smsReq.getCountryCode())) {
            smsReq.setCountryCode("234");
        }
        // 校验验证码当日发送次数
        checkSmsSendCount(smsReq, checkInterval);

        // 生成验证码
        String verifyCode = getVerifyCode(smsReq);
        // 根据短信类型查询短信模板
        JSONObject smsParam = new JSONObject();
        smsParam.put("verifyCode", verifyCode);
        SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_CODE).smsType(smsReq.getSmsType()).countryCode(smsReq.getCountryCode()).phoneNumber(smsReq.getPhoneNumber()).smsParam(smsParam).verifyCode(verifyCode).build();
        String content = getSmsContnet(smsData);
        log.info("Sms content is： {}", content);
        smsData.setContent(content);
        // 发送验证码
        String isServerSend = getIsServerSend(smsReq.getIsServerSend());
        log.info("----------------  send Sms start  发送验证码:" + isServerSend);
        if (StringUtils.equals(isServerSend, "1") && !codeSwitch()) {
            JSONObject jsonObject = smsSignUtil.encryptBASE64(smsData.getTmplateId());
            JSONObject data = new JSONObject();
            data.put("phoneNumber", smsData.getPhoneNumber());
            data.put("noticeType", smsData.getNoticeType());
            data.put("verifyCode", smsData.getVerifyCode());
            data.put("content", smsData.getContent());
            data.put("smsType", smsData.getSmsType());
            data.put("smsParam", smsData.getSmsParam());
            data.put("templateId", smsData.getTmplateId());
            jsonObject.put("data", data);
            try {
                String result = smsUtil.sendPost(smsSendConfig.getSendSms(), jsonObject, null);
                log.info(" -------- sms send success  :" + result);
            } catch (Exception e) {
                throw new BusinessException(RspEnmu.SMS_SEND_FAIL);
            }
        }
        // 缓存验证码
        smsData.setUuid(IdUtils.simpleUUID());
        cacheSmsCode(smsData);
//
//        // 保存验证码发送记录
        saveVerifyCodeLog(smsData);

        return smsData;
    }

    /**
     * 使用延期产品成功/失效/失败 及时短信
     */
    @Override
    @Async("threadPoolTaskExecutor")
    public void sendDelayProductSms(LoanIou loanIou, RepaymentOrder repaymentOrder, String type, String repayDate, MonnifyReservedAccount monnifyReservedAccount) {
        JSONObject smsParam = new JSONObject();
        UserInfo userInfo = userCacheService.getUserInfoByCustNo(repaymentOrder.getCustNo());
        String smsType = "";
        if (userInfo != null) {
            switch (type) {
                case SUCCESSFUL:// 成功
                    smsParam.put("last_name", userInfo.getLastName());
                    smsParam.put("deferred_repayment_date", repayDate);
                    BigDecimal remainingAmt = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
                    smsParam.put("remainingamt", remainingAmt.setScale(2, BigDecimal.ROUND_UP));
                    smsType = BizConstants.SMS_TYPE_MAIN_DFR_ACTV;
                    break;
                case DISABLED:// 失效
                    smsParam.put("last_name", userInfo.getLastName());
                    smsType = BizConstants.SMS_TYPE_MAIN_DFR_IACTV;
                    break;
                case FAILURE:// 失败
                    smsParam.put("last_name", userInfo.getLastName());
                    smsParam.put("vaaccountnumbe", monnifyReservedAccount.getAccountNumber());
                    smsParam.put("bankname", monnifyReservedAccount.getBankName());
                    smsType = BizConstants.SMS_TYPE_MAIN_DFR_PYMT_FAILED;
                    break;
            }
            SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE).smsType(smsType).phoneNumber(userInfo.getRegisterPhone()).countryCode(userInfo.getCountryCode()).smsParam(smsParam).build();
            sendSms(smsData);
        }

    }

//    /**
//     * t-1 t+0 t+1 延期产品短信
//     */
//    @Override
//    public int sendRepaymentSms(LoanIou loanIou, RealNameAuth realNameAuth, int iouStatus) {
//        JSONObject smsParam = new JSONObject();
//        ProductInfo productInfo = orderService.selectLoanOrderProduct(loanIou.getCustNo());
//        if (productInfo == null) {
//            return 0;
//        }
//        String smsType = null;
//        BigDecimal principal = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
//        List<ProductDeferredInfo> productDeferredInfoList = new ArrayList<>();
//        if(iouStatus == 2){
//            //查询有效的延期产品保留天数
//            productDeferredInfoList = deferredInfoMapper.getProductDerferedsForShow(productInfo.getId(), principal, loanIou.getPeriodNum(), productInfo.getDeferredMaxDays());
//        }
//        //有延期产品且没有使用
//        if (loanIou.getIsDeferred() == 0) {
//            switch (iouStatus) {
//                case 0://还款当日
//                    smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("credit_rating", sysConfigService.selectConfigKey(productInfo.getCreditRating()));
//                    smsParam.put("Remaining_Amt", loanIou.getLoanPrincipal().setScale(2, BigDecimal.ROUND_UP));
//                    smsParam.put("Repayment_date", loanIou.getRepayDate());
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_0;
//                    break;
//                case 2://逾期
//                    if (productDeferredInfoList.size() > 0 && DateUtils.apartDay(loanIou.getRepayDate()) < productDeferredInfoList.get(0).getNumDeferredRetainDay()) {
//                        smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                        smsParam.put("Remaining_Amt", loanIou.getOverdueAmount().setScale(2, BigDecimal.ROUND_UP));
//                        smsParam.put("overdueDay", DateUtils.apartDay(loanIou.getRepayDate()));
//                        smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_M1;
//                    }
//                    break;
//                case 1://还款前一天
//                    smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("credit_rating", sysConfigService.selectConfigKey(productInfo.getCreditRating()));
//                    smsParam.put("Repayment_date", loanIou.getRepayDate());
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_1;
//                    break;
//                case -2://还款前两天
//                    smsParam.put("last_name", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("vaaccountnumber", monnifyReservedAccount.getAccountNumber());
//                    smsParam.put("bankname", monnifyReservedAccount.getBankName());
//                    smsParam.put("mini_repay_amount", getMiniRepay(loanIou,productInfo).setScale(2, BigDecimal.ROUND_UP));
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_2;
//                    break;
//            }
//            if (smsType != null) {
//                SmsSendData smsData = SmsSendData.builder().smsType(smsType).noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE).countryCode("+234").phoneNumber(realNameAuth.getPhoneNumber()).smsParam(smsParam).build();
//                sendSms(smsData);
//                return 1;
//            }
//        }
//        return 0;
//    }

    /**
     * 还款成功 折扣产品及时短信
     */
    @Override
    public int sendRepaymentPassSms(String custNo, AppUser appUser) {
        JSONObject smsParam = new JSONObject();
        //判断当前用户是否满足 0利息/折扣利息 产品
        List<ProductInfo> productInfo = repaymentOrderService.selectCreditAccountProduct(custNo);
        productInfo.stream().sorted(Comparator.comparing(obj -> obj.getTags().contains("-1") ? 1 : 0)).collect(Collectors.toList());
        String smsType = null;
        if (productInfo.size() > 0) {
            for (int i = 0; i < productInfo.size(); i++) {
                String params = productInfo.get(i).getTags();
                smsParam.put("lastName", getRealNameAuth(appUser.getUserUuid()).getLastName());
                smsParam.put("credit_rating", sysConfigService.selectConfigKey(productInfo.get(i).getCreditRating()));
                smsParam.put("productperiod", productInfo.get(i).getPeriodNum());
                if (params.contains("-1")) {
                    smsParam.put("tags", "0 interest");
                } else if (params.contains("%")) {
                    BigDecimal multiply = ((productInfo.get(i).getShowInterestRate().subtract(productInfo.get(i).getInterestRate())).divide(productInfo.get(i).getShowInterestRate(), BigDecimal.ROUND_HALF_UP)).multiply(BigDecimal.valueOf(100)).setScale(0, BigDecimal.ROUND_HALF_UP);
                    smsParam.put("tags", multiply + "% interest discount");
                }
                smsType = BizConstants.SMS_TYPE_MAIN_RPY_0ORDISCINT;
                SmsSendData smsData = SmsSendData.builder().smsType(smsType).noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE).countryCode(appUser.getCountryCode()).phoneNumber(appUser.getPhone()).smsParam(smsParam).build();
                sendSms(smsData);
                break;
            }
            return 1;
        }
        return 0;
    }

    /**
     * t-1 t+0 t+1 延期产品短信
     */
    //@Override
//    public int sendRepaymentSms(LoanIou loanIou, RealNameAuth realNameAuth, int iouStatus) {
//        JSONObject smsParam = new JSONObject();
//        ProductInfo productInfo = orderService.selectLoanOrderProduct(loanIou.getCustNo());
//        if (productInfo == null) {
//            return 0;
//        }
//        String smsType = null;
//        BigDecimal principal = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
//        List<ProductDeferredInfo> productDeferredInfoList = new ArrayList<>();
//        if(iouStatus == 2){
//            //查询有效的延期产品保留天数
//            productDeferredInfoList = deferredInfoMapper.getProductDerferedsForShow(productInfo.getId(), principal, loanIou.getPeriodNum(), productInfo.getDeferredMaxDays());
//        }
//        //有延期产品且没有使用
//        if (loanIou.getIsDeferred() == 0) {
//            switch (iouStatus) {
//                case 0://还款当日
//                    smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("credit_rating", sysConfigService.selectConfigKey(productInfo.getCreditRating()));
//                    smsParam.put("Remaining_Amt", loanIou.getLoanPrincipal().setScale(2, BigDecimal.ROUND_UP));
//                    smsParam.put("Repayment_date", loanIou.getRepayDate());
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_0;
//                    break;
//                case 2://逾期
//                    if (productDeferredInfoList.size() > 0 && DateUtils.apartDay(loanIou.getRepayDate()) < productDeferredInfoList.get(0).getNumDeferredRetainDay()) {
//                        smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                        smsParam.put("Remaining_Amt", loanIou.getOverdueAmount().setScale(2, BigDecimal.ROUND_UP));
//                        smsParam.put("overdueDay", DateUtils.apartDay(loanIou.getRepayDate()));
//                        smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_M1;
//                    }
//                    break;
//                case 1://还款前一天
//                    smsParam.put("lastName", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("credit_rating", sysConfigService.selectConfigKey(productInfo.getCreditRating()));
//                    smsParam.put("Repayment_date", loanIou.getRepayDate());
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_1;
//                    break;
//                case -2://还款前两天
//                    smsParam.put("last_name", getRealNameAuth(realNameAuth.getUserId()).getLastName());
//                    smsParam.put("vaaccountnumber", monnifyReservedAccount.getAccountNumber());
//                    smsParam.put("bankname", monnifyReservedAccount.getBankName());
//                    smsParam.put("mini_repay_amount", getMiniRepay(loanIou,productInfo).setScale(2, BigDecimal.ROUND_UP));
//                    smsType = BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_2;
//                    break;
//            }
//            if (smsType != null) {
//                SmsSendData smsData = SmsSendData.builder().smsType(smsType).noticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE).countryCode("+234").phoneNumber(realNameAuth.getPhoneNumber()).smsParam(smsParam).build();
//                sendSms(smsData);
//                return 1;
//            }
//        }
//        return 0;
//    }
    protected RealNameAuth getRealNameAuth(String userId) {
        RealNameAuth auth = new RealNameAuth();
        auth.setUserId(userId);
        auth.setState(BizConstants.BIZ_STATUS_1);
        List<RealNameAuth> realNameAuthList = realNameAuthService.selectRealNameAuthList(auth);
        RealNameAuth realNameAuth = realNameAuthList.get(0);
        return realNameAuth;
    }

    private String getVerifyCode(SmsSendReq smsReq) {
        // 有效期内发送同一个验证码
        SmsSendVo smsVo = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_CODE).smsType(smsReq.getSmsType()).countryCode(smsReq.getCountryCode()).phoneNumber(smsReq.getPhoneNumber()).build();
        String smsKey = getSmsKey(smsVo);
        Object cacheObject = redisCache.getCacheObject(smsKey);

        boolean hasCache = cacheObject != null && !"".equals(cacheObject.toString());
        String verifyCode = hasCache ? cacheObject.toString() : getVerifyCode();
        return verifyCode;
    }

    private String getIsServerSend(String isServerSendReq) {
        String isServerSend = "1";
        if (StringUtils.isNotBlank(isServerSendReq)) {
            isServerSend = isServerSendReq;
        }
        return isServerSend;
    }

    /**
     * 短信发送同步方法，需要异步发送请移步 AsyncService.sendSms
     *
     * @param smsData
     * @return
     */
    @Override
    public int sendSms(SmsSendData smsData) {
        int responseCode = -1;
//        if (codeSwitch()) {
//            log.info("mock开启，模拟的短信内容为：{}", smsData.getContent());
//            return 200;
//        }
        if (StringUtils.isBlank(smsData.getContent())) {
            String content = this.getSmsContnet(smsData);
            smsData.setContent(content);
        }
        log.info("将要发送的短信内容为：{}", smsData.getContent());

        //发送短信规则
//        SmsAreaNumberConfigVO smsAreaNumberConfig = smsMapper.getSmsAreaNumberConfig(smsData.getPhoneNumber().substring(0, 4));
//        return super.sendSMSImpl(smsData, smsAreaNumberConfig);
        try {
//            responseCode = sendSmsByRule(smsData);
            JSONObject jsonObject = smsSignUtil.encryptBASE64(smsData.getTmplateId());
            JSONObject data = new JSONObject();
            data.put("phoneNumber", smsData.getPhoneNumber());
            data.put("noticeType", smsData.getNoticeType());
            data.put("verifyCode", smsData.getVerifyCode());
            data.put("content", smsData.getContent());
            data.put("smsType", smsData.getSmsType());
            data.put("smsParam", smsData.getSmsParam());
            data.put("templateId", smsData.getTmplateId());
            jsonObject.put("data", data);
            log.info("send sms request: " + JSON.toJSONString(jsonObject));
            String result = smsUtil.sendPost(smsSendConfig.getSendSms(), jsonObject, null);
            log.info("--------- send sms  :" + result);
            JSONObject json = JSONObject.parseObject(result);
            if (null != json && json.containsKey("code")) {
                responseCode = json.getInteger("code");
            }
        } catch (Exception e) {
            throw new BusinessException(RspEnmu.SMS_SEND_FAIL);
        }
        return responseCode;
    }

    @Override
    public String getSmsContnet(SmsSendData smsData) {
        SmsTemplate smsTemplate = new SmsTemplate();
        smsTemplate.setNoticeType(smsData.getNoticeType());
        smsTemplate.setSmsType(smsData.getSmsType());
        smsTemplate.setState("1");
        List<SmsTemplate> smsTemplateList = smsTemplateService.selectSmsTemplateList(smsTemplate);
        String content = smsTemplateList.get(0).getTemplateContent();

        if (content.contains(PARAM_MARK)) {
            content = replaceTemplateParams(content, smsData.getSmsParam());
        }

        return content;
    }

    @Override
    public List<VerifyCodeLog> verifyCodeLogCurDate(VerifyCodeLog verifyCodeLog) {
        return smsMapper.verifyCodeLogCurDate(verifyCodeLog);
    }

    @Override
    public void verifySmsCode(SmsSendVo smsVo) {
        // sms_code-register-8615768870644-1801834ba7574c659a6a4c6a365bd52e
        String redisKey = getSmsKey(smsVo);
        log.info("Sms's redisKey： {}", redisKey);
        String redisObject = redisCache.getCacheObject(redisKey);
        checkVerifyCode(smsVo.getVerifyCode(), redisObject);
        redisCache.deleteObject(redisKey);
    }

    private void previewSmsMessage(SmsSendData smsData, SendSmsApi sendSmsApi) {
        SmsPreviewResponse previewResponse = null;
        try {
            previewResponse = sendSmsApi.previewSmsMessage(new SmsPreviewRequest().text(smsData.getContent()));
            log.debug("这条消息中有这些字符将保留未使用", previewResponse);
        } catch (ApiException e) {
            log.error("Unicode和短信预览异常：code = {}, resBody = {}", e.getCode(), e.getResponseBody());
        }
    }


    private String getSmsKey(SmsSendVo smsVo) {
        // return BizConstants.SMS_CODE + "-" + smsVo.getSmsType() + "-" + smsVo.getCountryCode().replace("+", "") + smsVo.getPhoneNumber() + "-" + smsVo.getUuid();
        return Constants.SMS_CODE + "-" + smsVo.getSmsType() + "-" + smsVo.getCountryCode().replace("+", "") + smsVo.getPhoneNumber();
    }


    private void checkVerifyCode(String verifyCode, String redisObject) {
        if (redisObject == null) {
            throw new BusinessException(RspEnmu.GET_CODE_REPEAT);
        }

        if (!verifyCode.equals(redisObject)) {
            throw new BusinessException(RspEnmu.SMS_CODE_ERR);
        }
    }

    public static String replaceTemplateParams(String templateContent, JSONObject dataJson) {
        String smsContent = templateContent;

        Iterator<String> iterator = (Iterator<String>) dataJson.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = dataJson.getString(key);
            if (smsContent.contains(key)) {
                smsContent = smsContent.replace(PARAM_MARK + key + PARAM_MARK, value);
            }
        }
        return smsContent;
    }

    private void cacheSmsCode(SmsSendData smsData) {
        String redisKey = getSmsKey(smsData);
        log.info("[send] Sms's redisKey is {}", redisKey);
        //redisCache.setCacheObject(redisKey, smsData.getVerifyCode(), verifyCodeConfig.getEffectiveTime(), TimeUnit.SECONDS);
        redisCache.setCacheObject(redisKey, smsData.getVerifyCode(), verifyCodeConfig.getEffectiveTime(), TimeUnit.SECONDS);
        log.info("发送验证码，手机号 {} 验证码为：{}，uuid：{}", smsData.getPhoneNumber(), smsData.getVerifyCode(), smsData.getUuid());
    }

    private String getVerifyCode() {
        String verifyCode = VerifyCodeUtils.getSmsCode();
        if (codeSwitch()) {
            verifyCode = verifyCodeConfig.getMockValue();
        }
        return verifyCode;
    }

    private boolean codeSwitch() {
        return Integer.valueOf(getDictLable("biz_switch", "verify_code_mock")) == 1;
    }

    /**
     * @param smsReq
     * @param checkInterval 是否检查 发送的时间间隔
     */
    private void checkSmsSendCount(SmsSendReq smsReq, boolean checkInterval) {
        if (verifyCodeConfig.getMock() == 1) {
            return;
        }

        // 查询短信验证码当日发送次数
        VerifyCodeLog codeLog = new VerifyCodeLog();
        codeLog.setMobile(smsReq.getCountryCode() + smsReq.getPhoneNumber());
        codeLog.setSmsType(smsReq.getSmsType());

        List<VerifyCodeLog> verifyCodeLogList = this.verifyCodeLogCurDate(codeLog);
        if (CollectionUtils.isEmpty(verifyCodeLogList)) {
            return;
        }

        if (verifyCodeLogList.size() >= verifyCodeConfig.getCurDateCount()) {
            throw new BusinessException(RspEnmu.SMS_CODE_COUNT_LIMIT);
        }

        if (checkInterval && System.currentTimeMillis() - verifyCodeLogList.get(0).getCreateTime().getTime() < 60000) {
            throw new BusinessException(RspEnmu.SMS_CODE_SENT_IN_60_SECOND);
        }
    }

    private void saveVerifyCodeLog(SmsSendData smsData) {
        VerifyCodeLog codeLog = new VerifyCodeLog();
        codeLog.setVerifyCode(smsData.getVerifyCode());
        codeLog.setAppId(Constants.SMS_CODE);
        codeLog.setSmsType(smsData.getSmsType());
        codeLog.setUuid(smsData.getUuid());
        codeLog.setFingerprint(smsData.getFingerprint());
        codeLog.setMobile(smsData.getCountryCode() + smsData.getPhoneNumber());
        if (smsData.getSmsParam() != null && smsData.getSmsParam().containsKey("rspCode")) {
            codeLog.setRspCode(smsData.getSmsParam().getString("rspCode"));//响应状态码
        }
        if (smsData.getSmsParam() != null && smsData.getSmsParam().containsKey("rspMsg")) {
            codeLog.setRspMsg(smsData.getSmsParam().getString("rspMsg"));//响应信息
        }
        verifyCodeLogService.insertVerifyCodeLog(codeLog);
    }


    /**
     * 发送whatsApp 验证码
     *
     * @param smsReq
     * @return
     */
    @Override
    public SmsSendData sendWhatsAppVerifyCode(SmsSendReq smsReq) {
        if (StringUtils.isBlank(smsReq.getCountryCode())) {
            smsReq.setCountryCode("234");
        }
        // 校验验证码当日发送次数
        checkSmsSendCount(smsReq, true);

        SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_CODE)
                .smsType(smsReq.getSmsType()).countryCode(smsReq.getCountryCode())
                .phoneNumber(smsReq.getPhoneNumber()).noticeType("whatsApp").build();
        // 发送验证码
        String isServerSend = getIsServerSend(smsReq.getIsServerSend());
        if (StringUtils.equals(isServerSend, "1") && !codeSwitch()) {
//            this.sendSms(smsData);
            JSONObject jsonObject = smsSignUtil.encryptBASE64(smsData.getTmplateId());
            jsonObject.put("channel", "whatsApp");
            JSONObject data = new JSONObject();
            data.put("phoneNumber", smsData.getPhoneNumber());
            data.put("noticeType", smsData.getNoticeType());
            data.put("smsType", smsData.getSmsType());
            jsonObject.put("data", data);
            try {
                String result = smsUtil.sendPost(smsSendConfig.getSendWhatsApp(), jsonObject, null);
                log.info(" -------- whatsApp send success  :" + result);
            } catch (Exception e) {
                throw new BusinessException(RspEnmu.WHATSAPP_SEND_FAIL);
            }
        }
        // 缓存验证码
        smsData.setUuid(IdUtils.simpleUUID());
//        cacheSmsCode(smsData);
//        // 保存验证码发送记录
        saveVerifyCodeLog(smsData);

        return smsData;
    }

    @Override
    public SmsSendData sendFengRuanVoiceOtp(SmsSendReq smsReq) {
        if (StringUtils.isBlank(smsReq.getCountryCode())) {
            smsReq.setCountryCode("234");
        }
        // 校验验证码当日发送次数
        checkSmsSendCount(smsReq, true);

        // 生成验证码
        String verifyCode = getVerifyCode(smsReq);
        // 根据短信类型查询短信模板
        JSONObject smsParam = new JSONObject();
        smsParam.put("verifyCode", verifyCode);
        SmsSendData smsData = SmsSendData.builder().noticeType(BizConstants.SMS_NOTICE_TYPE_CODE).smsType(smsReq.getSmsType()).countryCode(smsReq.getCountryCode()).phoneNumber(smsReq.getPhoneNumber()).smsParam(smsParam).verifyCode(verifyCode).build();
        String content = getSmsContnet(smsData);
        log.info("Sms content is： {}", content);
        smsData.setContent(content);
        // 发送验证码
        String isServerSend = getIsServerSend(smsReq.getIsServerSend());
        log.info("----------------  send Sms start  发送语音验证码:" + isServerSend);
        if (StringUtils.equals(isServerSend, "1") && !codeSwitch()) {
//            this.sendSms(smsData);
            JSONObject jsonObject = smsSignUtil.encryptBASE64(smsData.getTmplateId());
            JSONObject data = new JSONObject();
            data.put("phoneNumber", smsData.getPhoneNumber());
            data.put("noticeType", smsData.getNoticeType());
            data.put("verifyCode", smsData.getVerifyCode());
            data.put("content", smsData.getContent());
            data.put("smsParam", smsData.getSmsParam());
            jsonObject.put("data", data);
            try {
                String result = smsUtil.sendPost(smsSendConfig.getSendVoiceOtp(), jsonObject, null);
                log.info(" -------- voiceOtp send success  :" + result);
            } catch (Exception e) {
                throw new BusinessException(RspEnmu.VOICE_SEND_FAIL);
            }
        }
        // 缓存验证码
        smsData.setUuid(IdUtils.simpleUUID());
        cacheSmsCode(smsData);
//        // 保存验证码发送记录
        saveVerifyCodeLog(smsData);
        return smsData;
    }

    @Override
    public boolean verifyWhatsAppCode(SmsSendData smsData) {
        JSONObject jsonObject = smsSignUtil.encryptBASE64(smsData.getTmplateId());
        JSONObject data = new JSONObject();
        data.put("phoneNumber", smsData.getPhoneNumber());
        data.put("verifyCode", smsData.getVerifyCode());
        jsonObject.put("data", data);
        boolean isVerify = false;
        try {
            String result = smsUtil.sendPost(smsSendConfig.getVerifyWhatsApp(), jsonObject, null);
            JSONObject resultJson = JSONObject.parseObject(result);
            isVerify = resultJson.getJSONObject("data").getBoolean("isVerify");
            log.info(" --------whatsApp verify success  :" + result);
        } catch (Exception e) {
            throw new BusinessException(RspEnmu.WHATSAPP_CHECK_FAIL);
        }
        return isVerify;
    }

    /**
     * 是主业务系统标识的
     **/
    private static boolean isLinkCredit(SmsTask smsTask) {
        if (StringUtils.isEmpty(smsTask.getTemplateId())) {
            return true;
        }
        SmsSignUtil.SmsTemplateEnum smsTemplateEnum = SmsSignUtil.SmsTemplateEnum.getEnum(smsTask.getTemplateId());
        if (smsTemplateEnum == null) {
            return true;
        }
        return false;
    }

    /**
     * 是CRM系统标识的
     **/
    private static boolean isCrm(SmsTask smsTask) {
        if (StringUtils.isEmpty(smsTask.getTemplateId())) {
            return false;
        }
        SmsSignUtil.SmsTemplateEnum smsTemplateEnum = SmsSignUtil.SmsTemplateEnum.getEnum(smsTask.getTemplateId());
        if (smsTemplateEnum == null) {
            return false;
        }
        if ("10002".equals(smsTemplateEnum.getAppId())) {
            return true;
        }
        return false;
    }

    /**
     * 是CNCS系统标识的
     **/
    private static boolean isCncs(SmsTask smsTask) {
        if (StringUtils.isEmpty(smsTask.getTemplateId())) {
            return false;
        }
        SmsSignUtil.SmsTemplateEnum smsTemplateEnum = SmsSignUtil.SmsTemplateEnum.getEnum(smsTask.getTemplateId());
        if (smsTemplateEnum == null) {
            return false;
        }
        if ("10003".equals(smsTemplateEnum.getAppId())) {
            return true;
        }
        return false;
    }

    /**
     * 批量短信发送
     *
     * @param smsTaskList
     */
    @Override
    public void sendBatchSms(List<SmsTask> smsTaskList) {
        try {
            List<SmsTask> linkCreditList = smsTaskList.stream().filter(SmsServiceImpl::isLinkCredit).collect(Collectors.toList());
            List<SmsTask> crmList = smsTaskList.stream().filter(SmsServiceImpl::isCrm).collect(Collectors.toList());
            List<SmsTask> cncsList = smsTaskList.stream().filter(SmsServiceImpl::isCncs).collect(Collectors.toList());
            this.sendBatchSmsByFlag(linkCreditList, "10001");
            this.sendBatchSmsByFlag(crmList, "10002");
            this.sendBatchSmsByFlag(cncsList, "10003");
        } catch (Exception e) {
            throw new BusinessException(RspEnmu.SMS_SEND_FAIL);
        }
    }

    /**
     * 根据系统标识批量发
     *
     * @param smsTaskList 短信任务
     * @param sysFlag     系统标识
     * @throws Exception
     */
    private void sendBatchSmsByFlag(List<SmsTask> smsTaskList, String sysFlag) throws Exception {
        if (CollectionUtils.isEmpty(smsTaskList)) {
            return;
        }
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < smsTaskList.size(); i++) {
            SmsTask smsTask = smsTaskList.get(i);
            //是否定期发送
            if (1 == Optional.ofNullable(smsTask.getIsTiming()).orElse(0)) {
                if (!DateUtils.dateTime(smsTask.getScheduleTime()).equals(DateUtils.dateTime(new Date()))) {
                    log.info("短信定时任务id:{} 不在指定发送日期", smsTask.getId());
                    continue;
                }
            }
            JSONObject json = new JSONObject();
            json.put("phoneNumber", smsTask.getPhone());
            json.put("noticeType", smsTask.getNoticeType());
            json.put("content", smsTask.getContent());
            json.put("smsType", smsTask.getSmsType());
            json.put("smsParam", smsTask.getSmsParam());
            json.put("templateId", smsTask.getTemplateId());
            jsonArray.add(json);
        }
        JSONObject jsonObject = smsSignUtil.encryptBASE64(SmsSignUtil.appIdMap.get(sysFlag));
        jsonObject.put("data", jsonArray);
        log.info("send sms request: " + JSON.toJSONString(jsonArray));
        String result = smsUtil.sendPost(smsSendConfig.getBatchSendSms(), jsonObject, null);
        log.info(String.format("--------- batch send sms [%s] : [%s]", sysFlag, result));
    }

    /**
     * 检查用户手机号是否注册
     *
     * @param userId 用户Id
     */
    @Override
    public void chenkPhone(String userId) {
//        //获取手机号
//        AppUser appUser=appUserMapper.selectPhoneByUserId(userId);
//        //用户手机号是否有效
//        AppUser appUser = appUserMapper.selectUser(phone);
//        if(appUser!=null){
//            throw new BusinessException(RspEnmu.USER_EXIST);
//        }
    }

    protected String getDictLable(String dictType, String dictValue) {
        return sysDictDataService.selectDictLabel(dictType, dictValue);
    }

}

